package com.chucang.shucang.log.executor;

import com.chucang.shucang.common.base.constant.CommonConstant;
import lombok.RequiredArgsConstructor;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.function.BiConsumer;

import static org.mybatis.spring.SqlSessionUtils.closeSqlSession;

/**
 * @author flitsneak
 * @email flitsneak@gmail.com
 * @date 2022/9/14 15:52
 * @description mybatis 开启batch模式
 */
@Component
@RequiredArgsConstructor
public class MybatisBatchExecutor {

    private final SqlSessionTemplate sqlSessionTemplate;


    /**
     * batch模式
     *
     * @param dataList
     * @param daoClass
     * @param bc
     * @param <T>
     * @param <D>
     */
    public <T, D> void insertOrUpdateBatch(List<T> dataList, Class<D> daoClass, BiConsumer<List<T>, D> bc) {
        int lastIndex = CommonConstant.BATCH_COUNT;
        int lastSubmitIndex = 0;
        int total = dataList.size();
        SqlSessionFactory sqlSessionFactory = sqlSessionTemplate.getSqlSessionFactory();
        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
        D dao = sqlSession.getMapper(daoClass);

        try {
            if (total > CommonConstant.BATCH_COUNT) {
                for (int index = 0; index < total; ) {
                    if (lastIndex > total) {
                        List<T> list = dataList.subList(index, total);
                        bc.accept(list, dao);
                        sqlSession.flushStatements();
                        sqlSession.commit();
                        break;
                    } else {
                        List<T> list = dataList.subList(index, lastIndex);
                        bc.accept(list, dao);
                        if (lastSubmitIndex++ >= CommonConstant.COMMIT_COUNT) {
                            sqlSession.flushStatements();
                            sqlSession.commit();
                            lastSubmitIndex = 0;
                        }
                        index = lastIndex;
                        lastIndex = index + (CommonConstant.BATCH_COUNT - 1);
                    }
                }
            } else {
                bc.accept(dataList, dao);
                sqlSession.commit();
            }
        } finally {
            closeSqlSession(sqlSession, sqlSessionFactory);
        }

    }

}
